﻿/******************************************************************************
 * 【本类功能概述】                                 					      *
 *  版权所有（C）2015-20XX，迅龙创威                                          *
 *  保留所有权利。                                                            *
 ******************************************************************************
 *  作者 : <hughjk>
 *  创建时间: 2017-1-3 13:22:32
 *  文件描述: 界面代码生成器
 *****************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;
using Util;

//using CodeStage.AntiCheat.ObscuredTypes;

namespace UguiScriptCreate
{
    public class UguiGenerator
    {

        private static UguiGenerator instance = null;
        public static UguiGenerator Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new UguiGenerator();
                }
                return instance;
            }

        }

        private List<Node> _allNodeContainer = new List<Node>();
        private static List<string> _namelist = new List<string>();

        private Transform m_fatherNode;
        private CreateType m_CreateType;

        //模版路径RTS/Toole/UGUI/UguiScriptCreate/Configs
        public string TemplatePath = Application.dataPath + "/Script/Utilit/Toole/UGUI/UguiScriptCreate/Configs/";
        //到处路径
        public string ExportPath = Application.dataPath + "/Script/GameLogic/System/Ui/";
        //存档模块
        public string StorageTypePath = Application.dataPath + "/System/GameLogic/StorageModelSys/";
        private class Node
        {
            public int _TypeId;     //排序标识符
            public Transform _transform;
            public string _path;
            public TypeNode _TypeNode;
        }
        private enum NodeType
        {
            _Button = 1,
            _Image = 2,
            _BigImage = 3,
            _Text = 4,
            _GridLayoutGroup = 5,
            _Slider = 6,
            _Transform = 7,
            _GameObject = 8,

        }
        public enum CreateType
        {
            _Base,     //基础
            _Module,   //只更新组件类
            _LogicAndModule,//逻辑and组件
            _LogicAndModuleAndData,  //逻辑and基础and储存
            _ItemUi,        //Item项
            _ItemClass,
        }

        private class TypeNode
        {
            public NodeType _type;                   //当前类型
            public string _GlobalName = "";          //private Button m_XXButton;//1 全局的命名
            public string _MyName = "";              //m_XXButton//自己的名字
            public string _GainFind = "";            // m_XX = transform.Find("XXP").GetComponent<Button>();//2//初始化
            public string _Registered = "";          // m_XX.onClick.AddListener(ResponseXXButton);//3//注册按钮
            public string _Unregister = "";          // m_XX.onClick.RemoveAllListeners();//4//注销按钮
            public string _ResponseFunction = "";    //private void ResponseXXButton() { }//5//按钮相应函数
            public string _ValueName = "";           //public string m_XXV;//6 赋值的名字
            public string _Value = "";               //m_XX.spriteName = data.m_XXV;或者m_XX.text = data.m_XXV;
            public string _OnResponseButton = "";      //public UIEventListener.VoidDelegate ResponseXXButton;

            private int sortId = 0;//排序ID
            public TypeNode(Node _node)
            {
                Structure(_node, getObjType(_node._transform));
            }
            public TypeNode(Node _node, NodeType _type)
            {
                if (_type == NodeType._Transform)
                {
                    _type = getObjType(_node._transform);
                }
                Structure(_node, _type);
            }

            //构建节点代码
            private void Structure(Node _node, NodeType __type)
            {
                string _typeS = "";
                string _typeNameS = "";
                switch (__type)
                {
                    case NodeType._Button:
                        _typeS = "Button";
                        _typeNameS = "B";
                        _type = NodeType._Button;
                        break;
                    case NodeType._Image:
                        _typeS = "Image";
                        _typeNameS = "I";
                        _type = NodeType._Image;
                        break;
                    case NodeType._BigImage:
                        _typeS = "UITexture";
                        _typeNameS = "I";
                        _type = NodeType._BigImage;
                        break;
                    case NodeType._Text:
                        _typeS = "Text";
                        _typeNameS = "T";
                        _type = NodeType._Text;
                        break;
                    case NodeType._GridLayoutGroup:
                        _typeS = "GridLayoutGroup";
                        _typeNameS = "G";
                        _type = NodeType._GridLayoutGroup;
                        break;
                    case NodeType._Slider:
                        _typeS = "Scrollbar";
                        _typeNameS = "S";
                        _type = NodeType._Slider;
                        break;
                    case NodeType._Transform:
                        _typeS = "Transform";
                        _typeNameS = "";
                        _type = NodeType._Transform;
                        break;
                    case NodeType._GameObject:
                        _typeS = "GameObject";
                        _typeNameS = "";
                        _type = NodeType._GameObject;
                        break;
                    default:
                        _typeS = "Transform";
                        _typeNameS = "";
                        _type = NodeType._Transform;
                        break;
                }
                _MyName = "m_"/*+ _typeNameS+"_"*/ + CLL(_node._transform.name);
                _MyName = NameRepeat(_MyName, _node._transform, _typeNameS);
                _GlobalName = "public " + _typeS + " " + _MyName + ";";
                if (__type == NodeType._Transform)
                {
                    _GainFind = _MyName + " = _transform.Find(\"" + _node._path + "\");";
                    //_GainFind = _MyName + " = UIHelper.Child(_transform,\"" + _node._path + "\");";
                }
                else
                if (__type == NodeType._GameObject)
                {
                    _GainFind = _MyName + " = _transform.Find(\"" + _node._path + "\").gameObject;";
                    //_GainFind = _MyName + " = UIHelper.ChildObj(_transform,\"" + _node._path + "\");";
                }
                else if (__type == NodeType._Button)
                {
                    _GainFind = _MyName + " = _transform.Find(\"" + _node._path + "\").GetComponent<" + _typeS + ">();";
                    //_GainFind = _MyName + " = UIHelper.ChildObj(_transform,\"" + _node._path + "\");";

                    _Registered = "m_window." + _MyName + ".onClick.AddListener(Response" + CFL(_node._transform.name) + ");";
                    _Unregister = "m_window." + _MyName + ".onClick.RemoveAllListeners();";
                    //_Registered = "UIEventListener.Get(" + _MyName + ".gameObject).onClick += Response" + CFL(_node._transform.name) + ";";
                    //_Unregister = "UIEventListener.Get(" + _MyName + ".gameObject).onClick -= Response" + CFL(_node._transform.name) + ";";

                    _ResponseFunction = "/// <summary>" + CFL(_node._transform.name) + "</summary> \n private void Response" + CFL(_node._transform.name) + "() \n{\n\t Debug.Log(\"OK + " + _MyName + "\"); \n}";
                }
                else
                {
                    // _AwakeFind = _MyName + " = _transform.Find(\"" + _node._path + "\").GetComponent(typeof(" + _typeS + ")) as " + _typeS + ";";
                    _GainFind = _MyName + " = _transform.Find(\"" + _node._path + "\").GetComponent<" + _typeS + ">();";
                    // _GainFind = _MyName + " = UIHelper.SubComponentGet<" + _typeS + ">(_transform,\"" + _node._path + "\");";
                }
                //Item赋值需要
                if (__type == NodeType._Image)
                {
                    _ValueName = "/// <summary>" + _MyName + "</summary> \n public string " + _MyName + "V=\"\";";
                    _Value = _MyName + ".spriteName = data." + _MyName + "V;";
                }
                else if (__type == NodeType._Text)
                {
                    _ValueName = "/// <summary>" + _MyName + "</summary> \n public string " + _MyName + "V=\"\";";
                    _Value = _MyName + ".text = data." + _MyName + "V;";
                }
                else if (__type == NodeType._BigImage)
                {
                    _ValueName = "/// <summary>" + _MyName + "</summary> \n public string " + _MyName + "V=\"\";";
                    _Value = "UIHelper.SetTexture(" + _MyName + ", data." + _MyName + "V, true);";
                }
            }

            public string CFL(string str)//首字母大写
            {
                return str = str.Substring(0, 1).ToUpper() + str.Substring(1);
            }
            public string CLL(string str)//首字母小写
            {
                return str = str.Substring(0, 1).ToLower() + str.Substring(1);
            }
            public string NameRepeat(string _name, Transform _transform, string _typeN)//名字重复问题
            {
                string name = "";
                if (_namelist.Contains(_name))
                {
                    int id = 0;
                    while (true)
                    {
                        string _endName = "";
                        if (id == 0)
                        {
                            _endName = "m_" + _transform.parent.name + CFL(_transform.name) + _typeN;
                            id++;
                            sortId = id;
                        }
                        else
                        {
                            _endName = "m_" + _transform.parent.name + CFL(_transform.name) + _typeN + id;
                            id++;
                            sortId = id;
                        }

                        if (!_namelist.Contains(_endName))
                        {
                            name = _endName;
                            _namelist.Add(_endName);
                            break;
                        }
                    }
                }
                else
                {
                    name = _name;
                    _namelist.Add(name);
                }
                return name;
            }
            public int getType()
            {
                return (int)(_type) * 100 + sortId;
            }
        }
        //获取判断类型
        private static NodeType getObjType(Transform obj)
        {
            if (obj.GetComponent<Button>())
            {
                return NodeType._Button;
            }
            else if (obj.GetComponent<Scrollbar>())
            {
                return NodeType._Slider;
            }
            else if (obj.GetComponent<Image>())
            {
                return NodeType._Image;
            }
            else if (obj.GetComponent<GridLayoutGroup>())
            {
                return NodeType._GridLayoutGroup;
            }
            else if (obj.GetComponent<Text>())
            {
                return NodeType._Text;
            }
            //         else if (obj.GetComponent<UITexture>())
            //         {
            //             return NodeType._BigImage;
            //         }
            else
            {
                return NodeType._GameObject;
            }
        }

        private class sortComparer : IComparer<Node>
        {
            public int Compare(Node AF1, Node AF2)
            {
                int res = 0;
                if (AF1._TypeId > AF2._TypeId)
                {
                    res = 1;
                }
                else if (AF1._TypeId < AF2._TypeId)
                {
                    res = -1;
                }
                return res;
            }
        }
        /// <summary>
        /// 查询代码的节点,与需要排除代码的节点.---------------------------------------------------------------入口----------------------------------------------------------------------------
        /// </summary>
        public string Manufacturing(Transform[] SelectionAsset, CreateType type)
        {
            m_CreateType = type;
            int MinDepth = 999;//深度
            int id = 0;
            Transform node = null;
            List<string> ExclusionLists = new List<string>();

            for (int i = 0; i < SelectionAsset.Length; i++)
            {
                int curD = getDepth(SelectionAsset[i]);
                if (curD < MinDepth)
                {
                    MinDepth = curD;
                    id = i;
                }
            }
            for (int i = 0; i < SelectionAsset.Length; i++)
            {
                if (i == id)
                {
                    node = SelectionAsset[i];
                }
                else
                {
                    ExclusionLists.Add(SelectionAsset[i].name);
                }
            }
            return Manufacturing(node, ExclusionLists);
        }
        //获取深度
        private int getDepth(Transform _node, Transform _pre = null)
        {
            int depth = 0;

            Transform m_curTransform = null;
            string RootName;

            RootName = _node.root.name;
            if (_pre != null)
            {
                RootName = _pre.name;
            }
            if (RootName != _node.name)
            {
                m_curTransform = _node;
                m_curTransform = m_curTransform.parent;
                depth++;
                while (!RootName.Equals(m_curTransform.name.ToString()))
                {
                    depth++;
                    m_curTransform = m_curTransform.parent;
                }
            }
            return depth;
        }


        /// <summary>
        /// 根据当前节点制造代码,顶部节点,需要排除的节点的名字,返回制造的代码-->注意:排除的名字一定不要有相同的
        /// </summary>
        public string Manufacturing(Transform _node, List<string> _ExclusionLists = null)
        {
            m_fatherNode = _node;
            ScreeningOfNode(_node, _ExclusionLists);
            return JoiningTogether();
        }
        //筛选节点
        public void ScreeningOfNode(Transform _node, List<string> _ExclusionLists = null)
        {
            _allNodeContainer = new List<Node>();
            _namelist = new List<string>();

            Transform[] _cur = _node.GetComponentsInChildren<Transform>();

            if (_cur.Length == 1)//只有一个,那就是他本身罗
            {
                Node _couNode = new Node();
                _couNode._transform = _cur[0];
                _couNode._path = RootPath(_cur[0]);
                _couNode._TypeNode = new TypeNode(_couNode, NodeType._Transform);
                _couNode._TypeId = _couNode._TypeNode.getType();
                _allNodeContainer.Add(_couNode);
            }
            else
            {
                for (int i = 0; i < _cur.Length; i++)
                {
                    if (Filter(_cur[i], _node))//过滤掉不需要的
                    {
                        continue;
                    }
                    Node _couNode = new Node();
                    _couNode._transform = _cur[i];
                    _couNode._path = RootPath(_cur[i], _node);

                    //检查是否需要跳过排除项
                    bool isExclusion = false;
                    if (_ExclusionLists != null && _ExclusionLists.Count > 0)
                    {
                        for (int j = 0; j < _ExclusionLists.Count; j++)
                        {
                            if (_couNode._path.Contains(_ExclusionLists[j] + "/"))
                            {
                                isExclusion = true;
                                break;
                            }
                        }
                    }
                    if (isExclusion)
                    {
                        continue;
                    }
                    _couNode._TypeNode = new TypeNode(_couNode);
                    _couNode._TypeId = _couNode._TypeNode.getType();

                    _allNodeContainer.Add(_couNode);

                }
                _allNodeContainer.Sort(0, _allNodeContainer.Count, new sortComparer());
            }
        }
        //获取路径
        public string RootPath(Transform _node, Transform _root = null)
        {
            string path = "";
            Transform m_curTransform = null;
            string RootName;
            if (_root == null)
            {
                _root = _node.root;
            }
            RootName = _root.name;
            if (RootName != _node.name)
            {
                m_curTransform = _node;
                path = m_curTransform.name;
                m_curTransform = m_curTransform.parent;

                while (!RootName.Equals(m_curTransform.name.ToString()))
                {
                    path = path.Insert(0, m_curTransform.name.ToString() + "/");
                    m_curTransform = m_curTransform.parent;
                }
            }
            return path;

        }
        //拼接代码
        public string JoiningTogether()
        {
            string _GlobalName = "Transform _transform;\n";
            string _init = " _transform=transform;\n";

            string _allRegister = "";
            string _allUnregister = "";
            string _GlobalFunction = "";

            string _ValueName = "";
            string _Value = "";
            NodeType _curNodeType = NodeType._Transform;
            for (int i = 0; i < _allNodeContainer.Count; i++)
            {
                if (_curNodeType != _allNodeContainer[i]._TypeNode._type)
                {
                    _curNodeType = _allNodeContainer[i]._TypeNode._type;
                    _GlobalName += "\n";
                    _init += "\n";
                }

                _GlobalName += "/// <summary>" + _allNodeContainer[i]._TypeNode._MyName + "</summary> \n[HideInInspector]\n" + _allNodeContainer[i]._TypeNode._GlobalName + '\n';
                _init += _allNodeContainer[i]._TypeNode._GainFind + '\n';
                if (_allNodeContainer[i]._TypeNode._type == NodeType._Button)
                {
                    _allRegister += _allNodeContainer[i]._TypeNode._Registered + '\n';
                    _allUnregister += _allNodeContainer[i]._TypeNode._Unregister + '\n';
                    _GlobalFunction += _allNodeContainer[i]._TypeNode._ResponseFunction + '\n';
                }
                else if (_allNodeContainer[i]._TypeNode._type == NodeType._Image ||
                         _allNodeContainer[i]._TypeNode._type == NodeType._Text ||
                         _allNodeContainer[i]._TypeNode._type == NodeType._BigImage)
                {
                    _ValueName += _allNodeContainer[i]._TypeNode._ValueName + '\n';
                    _Value += _allNodeContainer[i]._TypeNode._Value + '\n';
                }
            }

            string _all = Combination(_GlobalName, _init, _allRegister, _allUnregister, _GlobalFunction, _ValueName, _Value);
            return _all;
        }

        public string Combination(string name, string init, string register, string unregister, string responseFunction, string valueName, string value)
        {
            StringBuilder _all = new StringBuilder();
            string _boundary = "\n//----------------------------------------------------------------------\n";
            //string _banner = "/******************************************************************************\n * 【本类功能概述】                                 					      *\n *  版权所有（C）2015-20XX，迅龙创威                                          *\n *  保留所有权利。                                                            *\n ******************************************************************************\n *  作者 : <hughjk>\n *  创建时间:<time>\n *  文件描述:\n *****************************************************************************/\n";
            //_banner = _banner.Replace("<time>", System.DateTime.Now.ToString());
            string _UIInfo;
            string _Awake;
            string _Enable;
            string _Disable;
            string _Register;
            string _Unregister;
            string _execute;
            string _class;
            string _data;
            string mianName = m_fatherNode.name.Replace("Active", "").Replace("Info", "");
            Func<StringBuilder, StringBuilder> rep = (s) =>
            {
                return s.Replace("<mianName>", mianName)
                    .Replace("<name>", name)
                    .Replace("<init>", init)
                    .Replace("<register>", register)
                    .Replace("<unregister>", unregister)
                    .Replace("<responseFunction>", responseFunction)
                    .Replace("<time>", System.DateTime.Now.ToString());
            };
            switch (m_CreateType)
            {
                case CreateType._Base:
                    _all.Append(name);
                    _all.Append(_boundary);
                    _all.Append(init);
                    _all.Append(_boundary);
                    _all.Append(register);
                    _all.Append(_boundary);
                    _all.Append(unregister);
                    _all.Append(_boundary);
                    _all.Append(responseFunction); ;
                    break;
                case CreateType._Module:
                    {
                        var uiInfo = FileIO.Load(TemplatePath, "UiInfo.txt");
                        uiInfo = rep(uiInfo);
                        string ptah = ExportPath + mianName;
                        FileIO.Save(ptah, string.Format("/Ui{0}Info.cs", mianName), uiInfo.ToString());
                        _all.Append(uiInfo);
                    }
                    break;
                case CreateType._LogicAndModule:
                    {
                        var uiInfo = FileIO.Load(TemplatePath, "UiInfo.txt");
                        var formLogic = FileIO.Load(TemplatePath, "FormLogic.txt");

                        uiInfo = rep(uiInfo);
                        formLogic = rep(formLogic);

                        string ptah = ExportPath + mianName;

                        FileIO.Save(ptah, string.Format("/Ui{0}Info.cs", mianName), uiInfo.ToString());
                        FileIO.Save(ptah, string.Format("/Ui{0}Logic.cs", mianName), formLogic.ToString());

                        _all.Append(uiInfo);
                        _all.Append(formLogic);
                    }
                    break;
                case CreateType._LogicAndModuleAndData:
                    {
                        var uiInfo = FileIO.Load(TemplatePath, "UiInfo.txt");
                        var formLogic = FileIO.Load(TemplatePath, "FormLogic.txt");
                        var modelData = FileIO.Load(TemplatePath, "ModelData.txt");
                        var StorageType = FileIO.Load(StorageTypePath, "StorageType.cs");


                        uiInfo = rep(uiInfo);
                        formLogic = rep(formLogic);
                        modelData = rep(modelData);

                        Regex reg = new Regex(@"\[(.+?)]");
                        int STNum = reg.Match(StorageType.ToString()).Groups[1].Value.toInt();
                        StorageType = StorageType
                            .Replace("/*<Enum>*/", string.Format("{0}={1},\n\t\t/*<Enum>*/", mianName, STNum))
                            .Replace(string.Format("/*Num[{0}]*/", STNum), string.Format("/*Num[{0}]*/", (STNum + 1)))
                            .Replace("/*<AddData>*/", string.Format("m_AllModelData.Add(StorageModelType.{0}, new Storage{1}Model());\n\t\t\t/*<AddData>*/", mianName, mianName));


                        string ptah = ExportPath + mianName;
                        FileIO.Save(ptah, string.Format("/Ui{0}Info.cs", mianName), uiInfo.ToString());
                        FileIO.Save(ptah, string.Format("/Ui{0}Logic.cs", mianName), formLogic.ToString());
                        FileIO.Save(ptah, string.Format("/Storage{0}Model.cs", mianName), modelData.ToString());
                        FileIO.Save(StorageTypePath, "StorageType.cs", StorageType.ToString());

                        _all.Append(uiInfo);
                        _all.Append(formLogic);
                        _all.Append(modelData);
                        debug.logs(false, () =>
                        {
                            debug.log(uiInfo.ToString());
                            debug.log(formLogic.ToString());
                            debug.log(modelData.ToString());
                            debug.log(_all.ToString());
                        });

                    }

                    break;
                case CreateType._ItemUi:
                    {
                        _UIInfo = "\nusing UnityEngine;\n /// <summary><mianName></summary>\n   public class UI<mianName>Item : MonoBehaviour\n{\n<closs>\n}";
                        _Awake = "\n public void Awake()\n{\n<init>\n executeInit();\n}";
                        _Enable = "\n void OnEnable()\n{\nRegisterAllMessages();\nmReset();\n}";
                        _Disable = "\n void OnDisable()\n{\nUnregisterAllMessages();\n}";
                        _Register = "\n private void RegisterAllMessages(){<register>}";
                        _Unregister = "\n private void UnregisterAllMessages(){<unregister>}";
                        _execute = "\n private void executeInit()\n{\n}\n private void mReset()\n{\n}";

                        _class = name + _Awake + _Enable + _Disable + _Register + _Unregister + _execute + responseFunction;
                        _UIInfo = _UIInfo.Replace("<mianName>", m_fatherNode.name).Replace("<closs>", _class);
                        _all.Append(_UIInfo);
                        _all = _all.Replace("<init>", init).Replace("<register>", register).Replace("<unregister>", unregister);


                        string ptah = ExportPath + mianName;
                        FileIO.Save(ptah, string.Format("/{0}Item.cs", mianName), _all.ToString());
                    }
                    break;
                case CreateType._ItemClass:
                    {
                        _UIInfo = "\n /// <summary><mianName></summary>\n   public class UI<mianName> \n{\n<closs>\n}";
                        _data = "\n public BasicItemView m_lbitem;\n /// <summary>设置数据</summary>\npublic class Data\n{\n<data>}\n";
                        _Awake = "\n public void Init(Transform transform)\n{\n<init>\n m_lbitem = UIHelper.ComponentGet<BasicItemView>(_transform);\nm_lbitem.upData = mReset;\n}";
                        _execute = "\n public void mReset(object updateData)\n{\nData data = updateData as Data;\n<updata>}";
                        _class = name + _data + _Awake + _execute;
                        _UIInfo = _UIInfo.Replace("<mianName>", m_fatherNode.name).Replace("<closs>", _class);
                        _UIInfo = _UIInfo.Replace("<data>", valueName).Replace("<updata>", value).Replace("<init>", init).Replace("\n[HideInInspector]", "");
                        _all.Append(_UIInfo);

                        string ptah = ExportPath + mianName;
                        FileIO.Save(ptah, string.Format("/{0}.cs", mianName), _all.ToString());
                    }
                    break;
                default:
                    break;
            }

            return _all.ToString();
        }

        //判断首字母大写
        private bool isCapital(string name)
        {
            char[] c = name.ToCharArray();
            if (c[0] >= 'A' && c[0] <= 'Z')
            {
                return true;
            }
            return false;
        }
        //过滤器//tru标识不同通过
        private bool Filter(Transform name, Transform perNmae)
        {
            if (perNmae.name == name.name)//过滤
            {
                return true;
            }

            if (/*getDepth(name, perNmae) == 3 &&*/
                isCapital(name.name))
            {
                return false;
            }
            //else
            {
                return true;
            }
        }

    }
}
